package model

import (
	"errors"
	"fmt"
	"github.com/imroc/req"
	"net/url"
	"strings"
)

type GithubBranchesResult struct {
	Name   string `json:"name"`
	Commit struct {
		Sha string `json:"sha"`
		Url string `json:"url"`
	} `json:"commit"`
	Protected     bool   `json:"protected"`
	ProtectionUrl string `json:"protection_url"`
}

type GithubRepoResult struct {
	ID int `json:"id"`
}

type GithubCreateWebHookResult struct {
	Active bool `json:"active"`
	Config struct {
		ContentType string `json:"content_type"`
		InsecureSsl string `json:"insecure_ssl"`
		URL         string `json:"url"`
	} `json:"config"`
	CreatedAt    string   `json:"created_at"`
	Events       []string `json:"events"`
	ID           uint     `json:"id"`
	LastResponse struct {
		Code    interface{} `json:"code"`
		Message interface{} `json:"message"`
		Status  string      `json:"status"`
	} `json:"last_response"`
	Name      string `json:"name"`
	PingURL   string `json:"ping_url"`
	TestURL   string `json:"test_url"`
	Type      string `json:"type"`
	UpdatedAt string `json:"updated_at"`
	URL       string `json:"url"`
}

type GithubDelWebHookResult struct {
	ContentType string `json:"content_type"`
	InsecureSsl string `json:"insecure_ssl"`
	Secret      string `json:"secret"`
	URL         string `json:"url"`
}

type Github struct {
	url         string
	accessToken string
	parse       *url.URL
	search      []string
}

func NewGithub(_url string) (*Github, error) {
	_urlParse, err := url.Parse(_url)
	if err != nil {
		return &Github{}, err
	}
	search := strings.Split(strings.Replace(_urlParse.Path, ".git", "", -1), "/")
	if len(search) < 3 {
		return &Github{}, errors.New("less is short")
	}
	AccessToken, _ := _urlParse.User.Password()
	return &Github{url: _url, parse: _urlParse, search: search, accessToken: AccessToken}, nil
}

//获取分支信息
func (m *Github) GetBranches() (results []GithubBranchesResult, err error) {
	err = nil
	NewUrl := "https://api.github.com/repos/" + m.search[1] + "/" + m.search[2] + "/branches"
	if m.accessToken != "" {
		NewUrl += "?access_token=" + m.accessToken
	}
	header := req.Header{"Accept": "application/vnd.github.v3+json"}
	r, err := req.Get(NewUrl, header)
	if err != nil {
		return
	}
	if r.Response().StatusCode != 200 {
		err = errors.New(fmt.Sprintf("%v", r))
		return
	}
	err = r.ToJSON(&results)
	if results == nil {
		err = errors.New("请确认该仓库是否有权限！ ")
		return
	}
	if err != nil {
		return
	}
	return
}

//获取仓库信息
func (m *Github) GetReposId() (RepId int) {
	RepId = 0
	NewUrl := "https://api.github.com/repos/" + m.search[1] + "/" + m.search[2] + ""
	if m.accessToken != "" {
		NewUrl += "?access_token=" + m.accessToken
	}
	header := req.Header{"Accept": "application/vnd.github.v3+json"}
	r, err := req.Get(NewUrl, header)
	if err != nil {
		return
	}
	if r.Response().StatusCode != 200 {
		err = errors.New(fmt.Sprintf("%v", r))
		return
	}
	var results GithubRepoResult
	err = r.ToJSON(&results)
	if err != nil {
		return
	}
	RepId = results.ID
	return
}

//创建钩子
//https://docs.github.com/cn/rest/reference/repos#create-a-repository-webhook
func (m *Github) CreateWebHook(url, password string) (results GithubCreateWebHookResult, err error) {
	NewUrl := "https://api.github.com/repos/" + m.search[1] + "/" + m.search[2] + "/hooks"
	if m.accessToken != "" {
		NewUrl += "?access_token=" + m.accessToken
	}

	param := make(map[string]map[string]interface{})
	param["config"] = make(map[string]interface{})
	param["config"]["url"] = url
	param["config"]["content_type"] = "json"
	param["config"]["secret"] = password  //如果提供了该密钥，则该密钥将用作生成传递签名头的HMAC十六进制摘要值的密钥。
	param["config"]["insecure_ssl"] = "0" //确定在传递有效负载时是否验证url主机的SSL证书。支持的值包括0（已执行验证）和1（未执行验证）。默认值为0。我们强烈建议不要将此设置为1，因为您会受到中间人和其他攻击。
	param["config"]["token"] = ""         //undefined
	param["config"]["digest"] = ""        //undefined
	param["config"]["events"] = "push"    //事件
	param["config"]["active"] = true      //确定触发webhook时是否发送通知。设置为true可发送通知。
	header := req.Header{"Accept": "application/vnd.github.v3+json"}
	r, err := req.Post(NewUrl, header, req.BodyJSON(&param))
	if err != nil {
		return
	}
	if r.Response().StatusCode != 200 && r.Response().StatusCode != 201 {
		err = errors.New(fmt.Sprintf("%v", r))
		return
	}
	err = r.ToJSON(&results)
	if err != nil {
		return
	}
	return
}

//删除钩子
func (m *Github) DeleteWebHook(id string) (err error) {
	NewUrl := "https://api.github.com/repos/" + m.search[1] + "/" + m.search[2] + "/hooks/" + id
	if m.accessToken != "" {
		NewUrl += "?access_token=" + m.accessToken
	}
	header := req.Header{"Accept": "application/json;charset=UTF-8"}
	r, err := req.Delete(NewUrl, header)
	if err != nil {
		return
	}
	if r.Response().StatusCode != 204 {
		err = errors.New(fmt.Sprintf("%v", r))
		return
	}
	return
}
